package com.naiterui.ehp.bp.support.mvc;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.stream.IntStream;

import org.springframework.core.MethodParameter;
import org.springframework.lang.NonNull;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import com.google.common.base.Charsets;

import lombok.extern.slf4j.Slf4j;

/**
 * HeaderDecode 注解解析类，如果在spring mvc 中使用此注解，会将传递过来的参数解码
 *
 * @author wangzehao
 * @date 2018/11/19 5:14 PM
 * @since 1.0.0
 */
@Slf4j
public class HeaderDecodeArgResolverHandler implements HandlerMethodArgumentResolver {

    @Override
    public boolean supportsParameter(@NonNull MethodParameter methodParameter) {
        return methodParameter.hasParameterAnnotation(RequestHeaderDecode.class);
    }

    @Override
    public Object resolveArgument(@NonNull MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer,
                                  @NonNull NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws IOException {

        // 获取Controller中的参数名
        String headerName = methodParameter.getParameterName();

        String[] headerValues = nativeWebRequest.getHeaderValues(headerName);
        if (headerValues == null) {
            return null;
        }
        String[] decodeHeaderValue = new String[headerValues.length];
        IntStream.range(0, headerValues.length).forEach(i -> {
            try {
                decodeHeaderValue[i] = URLDecoder.decode(headerValues[i], Charsets.UTF_8.name());
            } catch (UnsupportedEncodingException ignored) {
                log.warn("解码失败 headerName:{} parameter:{}", headerName, headerValues[i]);
                decodeHeaderValue[i] = headerValues[i];
            }
        });
        return (decodeHeaderValue.length == 1 ? decodeHeaderValue[0] : decodeHeaderValue);
    }
}
